#ifndef _KTV_RECT_H_
#define _KTV_RECT_H_

#include "ui_point.h"
#include "ui_std_ex.h"
#include "SDL/SDL.h"
#include <stdlib.h>
#include <math.h>

namespace UI
{

class UI_Rect
{
public:
	UI_Rect() : m_Left(0), m_Right(0), m_Top(0), m_Bottom(0) { }
	UI_Rect(const int left, const int top, const int right, const int bottom) : m_Left(left), m_Right(right), m_Top(top), m_Bottom(bottom) { }
	UI_Rect(const UI_Point& p1, const UI_Point& p2) : m_Left(p1.XPos()), m_Right(p2.XPos()), m_Top(p1.YPos()), m_Bottom(p2.YPos()) { }
	UI_Rect(const UI_Rect& r) : m_Left(r.m_Left), m_Right(r.m_Right), m_Top(r.m_Top), m_Bottom(r.m_Bottom) { }
	UI_Rect(const SDL_Rect& r) : m_Left(r.x), m_Right(r.x + r.w), m_Top(r.y), m_Bottom(r.y + r.h) { }
	UI_Rect(const std::string& str);
	virtual ~UI_Rect() { }
	void SetTop(const int top) { m_Top = top; }
	void SetLeft(const int left) { m_Left = left; }
	void SetRight(const int right) { m_Right = right; }
	void SetBottom(const int bottom) { m_Bottom = bottom; }
	int Top(void) const { return m_Top; }
	int Left(void) const { return m_Left; }
	int Right(void) const { return m_Right; }
	int Bottom(void) const { return m_Bottom; }
	UI_Point TopLeft(void) const { return UI_Point(m_Left, m_Top); }
	UI_Point TopRight(void) const { return UI_Point(m_Right, m_Top); }
	UI_Point BottomLeft(void) const { return UI_Point(m_Left, m_Bottom); }
	UI_Point BottomRight(void) const { return UI_Point(m_Right, m_Bottom); }
	UI_Point Center(void) const { return UI_Point((m_Left + m_Right) / 2, (m_Top + m_Bottom) / 2); }
	UI_Point CenterLeft(void) const { return UI_Point( m_Left, (m_Top + m_Bottom) / 2); }
	UI_Point CenterTop(void) const { return UI_Point( (m_Left + m_Right) / 2, m_Top ); }
	UI_Point CenterBottom(void) const { return UI_Point( (m_Left + m_Right) / 2, m_Bottom ); }
	UI_Point CenterRight(void) const { return UI_Point( m_Right, (m_Top + m_Bottom) / 2); }
	SDL_Rect SDLRect(void) const;
	int Width(void) const { return abs(m_Right - m_Left); }
	int Height(void) const { return abs(m_Bottom - m_Top); }
	UI_Rect SizeRect(void) const { return UI_Rect(0, 0, abs(m_Right - m_Left), abs(m_Bottom - m_Top)); }
	UI_Rect& operator=(const UI_Rect& r);
	UI_Rect operator+(const UI_Point& p) const;
	UI_Rect operator-(const UI_Point& p) const;
	bool operator==(const UI_Rect& r) const
		{ return (m_Left == r.m_Left && m_Top == r.m_Top && m_Right == r.m_Right && m_Bottom == r.m_Bottom); }
	bool operator!=(const UI_Rect& r) const
		{ return (m_Left != r.m_Left || m_Top != r.m_Top || m_Right != r.m_Right || m_Bottom != r.m_Bottom); }
	UI_Rect& Grow(int iGrowAmount);
	UI_Rect& Move(int iOffsetX, int iOffsetY);
	bool Overlaps(const UI_Rect& r) const;
	UI_Rect& ClipTo(const UI_Rect& r);
	enum ERelativePosition
	{
		RELPOS_INVALID = 0, //!< This usually indicates some form of error
		RELPOS_ABOVE = 1, //!< The point is above the top of the CRect
		RELPOS_BELOW = 2, //!< The point is below the bottom of the CRect
		RELPOS_LEFT = 4, //!< The point is to the left of the CRect
		RELPOS_RIGHT = 8, //!< The point is to the right of the CRect
		RELPOS_INSIDE = 16 //!< The point lies within the bounds of the CRect
	};
	unsigned int HitTest(const UI_Point& p) const;
	std::string ToString(void) const
		{ return stdex::itoa(m_Left) + "," + stdex::itoa(m_Top) + "," + stdex::itoa(m_Right) + "," + stdex::itoa(m_Bottom); }

protected:
	int m_Left;
	int m_Right;
	int m_Top;
	int m_Bottom;
};

}


#endif // _KTV_RECT_H_

